<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <div id="app"></div>
    <script>
        let data = { msg: '123' }
        let bucket = new WeakMap()
        /* 
        理解数据结构：
            1.  bucket -> 里面是 target是键
                target是对象
                    而值是map数据结构
                        map的键是key，也就是target里面的key
                            而target的key对应的值就是set数据结构里面存储了所有的affect副作用域函数  
                {
                    target1: {
                        key1: {fn1, fn2},
                        key2: {fn1, fn2}
                    },
                    target2: {
                        key3: {fn3, fn4},
                        key4: {fn5, fn6}
                    }
                }
        */
        let activeAffect
        let obj = new Proxy(data, {
            get(target, key) {
                // 1. 没有activeAffect 就直接return
                // 2. 从weakMap里面根据对象拿出map map就是一个对象 包括所有的属性和副作用域函数的对应关系
                // 3. 从map里面根据key，key就是对象的所有属性，拿出所有该属性对应的的副作用域的函数
                // 4. 所有的副作用域函数 添加到 depSet里面去
                track(target, key)
                console.log('访问数据了', target[key]);
                return target[key]
            },
            set(target, key, newVal) {
                // 1.从bucket里面，根据target这个对象，拿到一个all的副作用域函数的结合。记得判空
                // 2.根据key，从集合里面找到，该key对应的所有的副作用域函数
                // 3.然后执行所有的副作用域函数 记得判空
                console.log('数据更新了', target[key], '改为', newVal);
                target[key] = newVal
                // 这两句的顺序是不能够相反的
                trigger(target, key)
                // obj1.name = 123
                // weakMap(obj1, 123)
                // obj.name = 456
                // weakMap.get(obj1) =>还是123
            }
        })

        function track(target, key) {
            debugger
            if (!activeAffect) {
                return target[key]
            }

            let depMap = bucket.get(target)
            if (!depMap) {
                bucket.set(target, (depMap = new Map()))
            }

            let depSet = depMap.get(key)
            if (!depSet) {
                depMap.set(key, (depSet = new Set()))
            }
            depSet.add(activeAffect)
        }
        function trigger(target, key) {
            debugger
            let depMap = bucket.get(target)
            if (!depMap) return
            let effects = depMap.get(key)
            effects && effects.forEach(fn => fn())
        }

        function effect(fn) {
            debugger
            activeAffect = fn
            fn()
        }
        effect(() => {
            debugger
            document.querySelector('#app').innerHTML = obj.msg
        })
    </script>
</body>

</html>